home *** CD-ROM | disk | FTP | other *** search
/ Aminet 40 / Aminet 40 (2000)(Schatztruhe)[!][Dec 2000].iso / Aminet / game / shoot / ADoomPPC_src.lha / ADoomPPC_src / amiga_video.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-30  |  40.9 KB  |  1,439 lines

  1. #ifndef __GNUC__
  2. #define CallChunkyCopy ms.algo
  3. #endif
  4.  
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8.  
  9. #include "amiga_macros.h"
  10.  
  11. #include <exec/exec.h>
  12. #include <dos/dos.h>
  13. #include <dos/exall.h>
  14. #include <graphics/gfx.h>
  15. #include <graphics/gfxbase.h>
  16. #include <graphics/gfxmacros.h>
  17. #include <graphics/scale.h>
  18. #include <intuition/intuition.h>
  19. #include <libraries/asl.h>
  20. #include <libraries/lowlevel.h>
  21. #include <cybergraphics/cybergraphics.h>
  22. #include <devices/gameport.h>
  23. #include <devices/keymap.h>
  24.  
  25. #include <proto/exec.h>
  26. #include <proto/dos.h>
  27. #include <proto/graphics.h>
  28. #include <proto/layers.h>
  29. #include <proto/intuition.h>
  30. #include <proto/asl.h>
  31. #include <proto/keymap.h>
  32. #include <proto/lowlevel.h>
  33. #include <proto/cybergraphics.h>
  34.  
  35. #include <clib/alib_protos.h>
  36.  
  37. #ifdef GRAFFITI
  38. #include "graffiti.h"
  39. #include "graffiti_lib.h"
  40. #include "graffiti_protos.h"
  41. #endif
  42.  
  43. #ifdef CHUNKYPPC
  44. #ifdef __SASC
  45. #include "chunkyppc_protos.h"
  46. #else
  47. #include <clib/chunkyppc_protos.h>
  48. #endif
  49. #endif
  50.  
  51. #include "doomtype.h"
  52. #include "doomdef.h"
  53. #include "doomstat.h"
  54. #include "i_system.h"
  55. #include "i_video.h"
  56. #include "v_video.h"
  57. #include "m_argv.h"
  58. #include "m_bbox.h"
  59. #include "d_main.h"
  60.  
  61. #include "amiga_sega.h"
  62. #include "r_draw.h"
  63. #include "w_wad.h"
  64. #include "z_zone.h"
  65.  
  66. /**********************************************************************/
  67. void video_cleanup (void);
  68.  
  69. extern void ppctimer (unsigned int *time);
  70. extern int bus_MHz;
  71.  
  72. extern void ppc_c2p_line (int line, int src, struct BitMap *dst, int cnt);
  73.  
  74. extern struct ExecBase *SysBase;
  75. struct Library *AslBase = NULL;
  76. struct Library *CyberGfxBase = NULL;
  77. struct Library *LowLevelBase = NULL;
  78. struct Library *KeymapBase = NULL;
  79.  
  80. #ifdef CHUNKYPPC
  81. #ifdef WARPUP
  82. struct Library *ChunkyPPCBase;
  83. #endif
  84. static struct Mode_Screen ms;
  85. static struct Mode_Screen *msptr = NULL;
  86. static BOOL video_is_chunkyppc = FALSE;
  87. #endif
  88.  
  89. extern int cpu_type;
  90.  
  91. int SCREENWIDTH;
  92. int SCREENHEIGHT;
  93. int weirdaspect;
  94.  
  95.  
  96. #define NUMPALETTES 14
  97.  
  98. static struct ScreenModeRequester *video_smr = NULL;
  99. static struct Screen *video_screen = NULL;
  100. static struct Window *video_window = NULL;
  101.  
  102. static struct ScreenBuffer *SBuffer[3] = {NULL, NULL, NULL};
  103. static struct ScreenBuffer *NextSBuffer = NULL;
  104.  
  105. //static int video_mod = 320;
  106. //static ULONG video_pixfmt = PIXFMT_LUT8;
  107. //static ULONG *video_buffer = NULL;
  108.  
  109. static int video_depth = 8;
  110.  
  111. static FAR ULONG video_colourtable[NUMPALETTES][1 + 3*256 + 1];
  112. static int video_palette_index = 0;
  113. //static int video_pending_palette_index = 0;
  114. static volatile WORD video_palette_changed = 0;
  115.  
  116. static BOOL video_is_cyber_mode = FALSE;
  117. static BOOL video_is_directcgx = FALSE;
  118. static BOOL video_is_native = FALSE;
  119. static BOOL video_doing_fps = FALSE;
  120. static APTR video_bitmap_handle = NULL;
  121.  
  122. static struct RastPort video_temprp;
  123. static struct BitMap video_tmp_bm = {
  124.   0, 0, 0, 0, 0, {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}
  125. };
  126.  
  127. static UWORD *emptypointer;
  128.  
  129. /* keyboard */
  130. static BOOL video_is_rawkey;
  131.  
  132. /* gameport stuff */
  133. static struct MsgPort *gameport_mp = NULL;
  134. static struct IOStdReq *gameport_io = NULL;
  135. static BOOL gameport_is_open = FALSE;
  136. static BOOL gameport_io_in_progress = FALSE;
  137. static struct InputEvent gameport_ie;
  138. static BYTE gameport_ct;        /* controller type */
  139. struct GamePortTrigger gameport_gpt = {
  140.   GPTF_UPKEYS | GPTF_DOWNKEYS,    /* gpt_Keys */
  141.   0,                /* gpt_Timeout */
  142.   1,                /* gpt_XDelta */
  143.   1                /* gpt_YDelta */
  144. };
  145.  
  146. /* SEGA variables */
  147. static ULONG prevSega;
  148. static BOOL sega3_selected = FALSE;
  149. static BOOL sega6_selected = FALSE;
  150.  
  151. #ifdef GRAFFITI
  152. struct Library *GraffitiBase = NULL;
  153. int video_graffiti = 0;
  154. static struct GRF_Screen *video_grf_screen = NULL;
  155. #endif
  156.  
  157. #ifdef PROFILE
  158. unsigned int profile[32][4];
  159. #endif
  160.  
  161. /****************************************************************************/
  162.  
  163. static unsigned int start_time[2];
  164. static unsigned int wpa8_time = 0;
  165. static unsigned int lock_time = 0;
  166. static unsigned int c2p_time = 0;
  167. static unsigned int total_frames = 0;
  168. #ifdef CHUNKYPPC
  169. static unsigned int chunkyppc_time = 0;
  170. #endif
  171.  
  172. /****************************************************************************/
  173. static INLINE void start_timer (void)
  174. {
  175.   ppctimer (start_time);
  176. }
  177.  
  178. /****************************************************************************/
  179. static INLINE unsigned int end_timer (void)
  180. {
  181.   unsigned int end_time[2];
  182.  
  183.   ppctimer (end_time);
  184.   if (end_time[1] >= start_time[1])
  185.     return (((end_time[1] - start_time[1]) << 2) / bus_MHz);
  186.   else
  187.     return (((end_time[1] - start_time[1]) << 2) / bus_MHz + 1000000);
  188. }
  189.  
  190. /****************************************************************************/
  191.  
  192. static char *mode_name (ULONG mode)
  193. /* Return a mode name for given mode, compatible with ASL mode requester */
  194. /* Use name in DisplayInfo database if available */
  195. /* else manually construct the name */
  196. {
  197.   APTR handle;
  198.   char *p;
  199.   struct NameInfo nameinfo;
  200.   struct DimensionInfo dimsinfo;
  201.   static char modename[DISPLAYNAMELEN + 4 + 4 + 11 + 1];
  202.  
  203.   p = modename;
  204.   *p = '\0';
  205.   if ((handle = FindDisplayInfo (mode & ~SPRITES)) != NULL) {
  206.     if (GetDisplayInfoData (handle, (UBYTE *)&nameinfo,
  207.                             sizeof(nameinfo), DTAG_NAME,
  208.                             0) > sizeof(struct QueryHeader)) {
  209.       p += sprintf (p, "%s", nameinfo.Name);
  210.     } else if (GetDisplayInfoData (handle, (UBYTE *)&dimsinfo,
  211.                                    sizeof(dimsinfo), DTAG_DIMS,
  212.                                    0) >= 66 /* sizeof(dimsinfo)*/) {
  213.       switch (mode & MONITOR_ID_MASK) {
  214.         case DEFAULT_MONITOR_ID:
  215.           p += sprintf (p, "DEFAULT:");      /* PAL or NTSC??? */
  216.           break;
  217.         case NTSC_MONITOR_ID:
  218.           p += sprintf (p, "NTSC:");
  219.           break;
  220.         case PAL_MONITOR_ID:
  221.           p += sprintf (p, "PAL:");
  222.           break;
  223.         case VGA_MONITOR_ID:
  224.           p += sprintf (p, "MULTISCAN:");
  225.           break;
  226.         case A2024_MONITOR_ID:
  227.           p += sprintf (p, "A2024:");
  228.           break;
  229.         case PROTO_MONITOR_ID:
  230.           p += sprintf (p, "PROTO:");
  231.           break;
  232.         case EURO72_MONITOR_ID:
  233.           p += sprintf (p, "EURO72:");
  234.           break;
  235.         case EURO36_MONITOR_ID:
  236.           p += sprintf (p, "EURO36:");
  237.           break;
  238.         case SUPER72_MONITOR_ID:
  239.           p += sprintf (p, "SUPER72:");
  240.           break;
  241.         case DBLNTSC_MONITOR_ID:
  242.           p += sprintf (p, "DBLNTSC:");
  243.           break;
  244.         case DBLPAL_MONITOR_ID:
  245.           p += sprintf (p, "DBLPAL:");
  246.           break;
  247.         default:
  248.           p += sprintf (p, "(unknown):");
  249.           break;
  250.       }
  251.       p += sprintf (p, "%d x %d",
  252.                     dimsinfo.Nominal.MaxX - dimsinfo.Nominal.MinX + 1,
  253.                     dimsinfo.Nominal.MaxY - dimsinfo.Nominal.MinY + 1);
  254.       if ((mode & HAM_KEY) != 0)
  255.         p += sprintf (p, " HAM");
  256.       if ((mode & EXTRAHALFBRITE_KEY) != 0)
  257.         p += sprintf (p, " EHB");
  258.       if ((mode & LACE) != 0)
  259.         p += sprintf (p, " Interlaced");
  260.     } else {
  261.       p += sprintf (p, "%s", "(unnamed)");
  262.       if ((mode & HAM_KEY) != 0)
  263.         p += sprintf (p, " HAM");
  264.       if ((mode & EXTRAHALFBRITE_KEY) != 0)
  265.         p += sprintf (p, " EHB");
  266.       if ((mode & LACE) != 0)
  267.         p += sprintf (p, " Interlaced");
  268.     }
  269.   } else {
  270.     p += sprintf (p, "%s", "(unavailable)");
  271.   }
  272.   return (modename);
  273. }
  274.  
  275. /****************************************************************************/
  276.  
  277. static ULONG parse_mode (char *modename)
  278. /* Modename may be descriptive name ("PAL Lores"), or hex ("$00420001" or */
  279. /* "0x12345678") or decimal ("32768"). */
  280. {
  281.   ULONG mode, reason;
  282.  
  283.   mode = INVALID_ID;
  284.   if (modename != NULL) {
  285.     if (modename[0] == '0' && modename[1] == 'x') {
  286.       if (sscanf (&modename[2], "%lx", &mode) != 1)
  287.         mode = INVALID_ID;
  288.     } else if (modename[0] == '$') {
  289.       if (sscanf (&modename[1], "%lx", &mode) != 1)
  290.         mode = INVALID_ID;
  291.     } else if (modename[0] >= '0' && modename[0] <= '9') {
  292.       if (sscanf (modename, "%ld", &mode) != 1)
  293.         mode = INVALID_ID;
  294.     } else {
  295.       while ((mode = NextDisplayInfo (mode)) != INVALID_ID) {
  296.         if ((mode & LORESDPF_KEY) == 0) {
  297.           /* printf ("$%08x  \"%s\"\n", mode, mode_name (mode)); */
  298.           if (strcmp (mode_name (mode), modename) == 0)
  299.             break;
  300.         }
  301.       }
  302.     }
  303.   }
  304.   if (FindDisplayInfo (mode) == NULL)
  305.     I_Error ("ScreenMode not in database: \"%s\"", modename);
  306.   if ((reason = ModeNotAvailable (mode)) != 0)
  307.     I_Error ("Mode $%08x is not available: %ld", mode, reason);
  308.   return (mode);
  309. }
  310.  
  311. /**********************************************************************/
  312. static void video_do_fps (struct RastPort *rp, int yoffset)
  313. {
  314.   int x;
  315.   static unsigned int start_time[2] = {0, 0};
  316.   unsigned int end_time[2];
  317.   char msg[4];
  318.  
  319.   ppctimer (end_time);
  320.   if (end_time[1] >= start_time[1])
  321.     x = (((end_time[1] - start_time[1]) << 2) / bus_MHz);
  322.   else
  323.     x = (((end_time[1] - start_time[1]) << 2) / bus_MHz + 1000000);
  324.   if (x != 0) {
  325.     x = (1000000 + (x >> 1)) / x;   /* round to nearest */
  326.     msg[0] = (x % 1000) / 100 + '0';
  327.     msg[1] = (x % 100) / 10 + '0';
  328.     msg[2] = (x % 10) + '0';
  329.     msg[3] = '\0';
  330.     Move (rp, SCREENWIDTH - 24, yoffset + 6);
  331.     Text (rp, msg, 3);
  332.   }
  333.   start_time[1] = end_time[1];
  334. }
  335.  
  336. #ifdef CHUNKYPPC
  337. static void I_InitGraphicsCPPC (void)
  338. {
  339. #ifdef WARPUP
  340.     if ((ChunkyPPCBase = OpenLibrary("chunkyppc.library", 10)) == NULL)
  341.             I_Error("OpenLibrary(""chunkyppc.library"", 10) failed");
  342. #endif
  343.  
  344.     ms.SCREENWIDTH = SCREENWIDTH;
  345.     ms.SCREENHEIGHT = SCREENHEIGHT; 
  346.     ms.MS_MAXWIDTH = 1600;
  347.     ms.MS_MAXHEIGHT = 1280;
  348.     ms.MINDEPTH = 8;
  349.     ms.MAXDEPTH = 8;
  350.     ms.video_screen = 0;
  351.     ms.video_window = 0;
  352.     msptr = &ms;
  353.  
  354. #ifdef WARPUP
  355.     if (!(msptr = OpenGraphics("ADoomWOS", &ms, 2)))
  356. #else
  357.     if (!(msptr = OpenGraphics("ADoomPPC", &ms, 2)))
  358. #endif
  359.         I_Error("OpenGraphics() failed");
  360.  
  361.     if (!(ChunkyInit(&ms, PIXFMT_LUT8)))
  362.         I_Error("ChunkyInit() failed");
  363.  
  364.     printf ("Screen Mode $%08x is ", ms.mode);
  365.   printf ("8-BIT");
  366.      printf (" ChunkyPPC ");
  367.     if (ms.numbuffers == 1)
  368.         printf ("Single Buffered");
  369.     else if (ms.numbuffers == 2)
  370.         printf ("Double Buffered");
  371.     else
  372.         printf ("Triple Buffered");
  373.   printf ("\n");
  374.  
  375.     
  376.     video_depth = 8;
  377.     video_window = ms.video_window;
  378.  
  379.     if (!(M_CheckParm("-mouse")))
  380.         if(!(ModifyIDCMP(ms.video_window, IDCMP_RAWKEY)))
  381.             I_Error ("ModifyIDCMP() failed\n");
  382. }
  383. #endif
  384.  
  385. /**********************************************************************/
  386. // Called by D_DoomMain,
  387. // determines the hardware configuration
  388. // and sets up the video mode
  389. void I_InitGraphics (void)
  390. {
  391.   ULONG propertymask, idcmp, wflags, width, pixfmt;
  392.   struct Rectangle rect;
  393.   char reqtitle[32];
  394.   int mode, depth, nbytes, p;
  395.   DisplayInfoHandle handle;
  396.   struct DisplayInfo dispinfo;
  397.   struct DimensionInfo dimsinfo;
  398.   static struct TextAttr topaz8 = {
  399.     "topaz.font", 8, FS_NORMAL, FPF_ROMFONT
  400.   };
  401.  
  402.     atexit(video_cleanup);
  403.  
  404.   if ((KeymapBase = OpenLibrary ("keymap.library", 0)) == NULL)
  405.     I_Error ("Can't open keymap.library");
  406.  
  407.   video_doing_fps = M_CheckParm ("-fps");
  408.  
  409.     if (AslBase == NULL) {
  410.       if ((AslBase = OpenLibrary ("asl.library", 37L)) == NULL ||
  411.           (video_smr = AllocAslRequestTags (ASL_ScreenModeRequest, TAG_DONE)) == NULL) {
  412.         I_Error ("OpenLibrary(""asl.library"", 37) failed");
  413.       }
  414.     }
  415.  
  416. #ifdef CHUNKYPPC
  417.         video_is_chunkyppc = M_CheckParm ("-chunkyppc");
  418.         if (video_is_chunkyppc) {
  419.             I_InitGraphicsCPPC();
  420.         } else {
  421. #endif
  422. #ifdef GRAFFITI
  423.       if (video_graffiti != 0) {
  424.         if ((GraffitiBase = OpenLibrary ("graffiti.library", 0)) == NULL)
  425.           I_Error ("Can't open graffiti.library");
  426.         if ((video_grf_screen = OpenChunkyScreen (video_graffiti)) == NULL)
  427.           I_Error ("graffiti.library OpenChunkyScreen() failed");
  428.         video_screen = (struct Screen *)video_grf_screen->GRF_ScreenID;
  429.         video_depth = 8;
  430.       } else {
  431. #endif
  432.         CyberGfxBase = OpenLibrary ("cybergraphics.library", 0); /* may be NULL */
  433.  
  434.         /* first check tooltypes for SCREENMODE */
  435.         mode = -1;
  436.         p = M_CheckParm ("-screenmode");
  437.         if (p && p < myargc - 1) {
  438.           mode = parse_mode (myargv[p+1]);
  439.         }
  440.  
  441.         /* if not found in icon tooltypes, then put up a ScreenMode requester */
  442.         if (mode == -1) {
  443.           propertymask = DIPF_IS_EXTRAHALFBRITE | DIPF_IS_DUALPF |
  444.                                           DIPF_IS_PF2PRI | DIPF_IS_HAM;
  445.           if (CyberGfxBase != NULL)
  446.             mode = BestCModeIDTags (CYBRBIDTG_NominalWidth, SCREENWIDTH,
  447.                                     CYBRBIDTG_NominalHeight, SCREENHEIGHT,
  448.                                     CYBRBIDTG_Depth,    8,
  449.                                     TAG_DONE);
  450.           else if (GfxBase->LibNode.lib_Version >= 39)
  451.             mode = BestModeID (BIDTAG_NominalWidth,     SCREENWIDTH,
  452.                                BIDTAG_NominalHeight,    SCREENHEIGHT,
  453.                                BIDTAG_Depth,            video_depth,
  454.                                BIDTAG_DIPFMustNotHave,  propertymask,
  455.                                TAG_DONE);
  456.           if (AslBase->lib_Version >= 38) {
  457.             sprintf (reqtitle, "ADoomPPC %dx%d", SCREENWIDTH, SCREENHEIGHT);
  458.             if (!AslRequestTags (video_smr,
  459.                                  ASLSM_TitleText,        (ULONG)reqtitle,
  460.                                  ASLSM_InitialDisplayID, mode,
  461.                                  ASLSM_MinWidth,         SCREENWIDTH,
  462.                                  ASLSM_MinHeight,        SCREENHEIGHT,
  463.                                  ASLSM_MaxWidth,         MAXSCREENWIDTH,
  464.                                  ASLSM_MaxHeight,        MAXSCREENHEIGHT,
  465.                                  ASLSM_MinDepth,         8,
  466.                                  ASLSM_MaxDepth,         8,
  467.                                  ASLSM_PropertyMask,     propertymask,
  468.                                  ASLSM_PropertyFlags,    0,
  469.                                  TAG_DONE)) {
  470.               I_Error ("AslRequest() failed");
  471.             }
  472.             mode = video_smr->sm_DisplayID;
  473.           }
  474.         }
  475.  
  476.         if ((handle = FindDisplayInfo (mode)) == NULL) {
  477.           I_Error ("Can't FindDisplayInfo() for mode %08x", mode);
  478.         }
  479.         if ((nbytes = GetDisplayInfoData (handle, (UBYTE *)&dispinfo,
  480.                                           sizeof(struct DisplayInfo), DTAG_DISP,
  481.                                           0)) < 40 /*sizeof(struct DisplayInfo)*/) {
  482.           I_Error ("Can't GetDisplayInfoData() for mode %08x, got %d bytes",
  483.                    mode, nbytes);
  484.         }
  485.         if ((nbytes = GetDisplayInfoData (handle, (UBYTE *)&dimsinfo,
  486.                                           sizeof(dimsinfo), DTAG_DIMS,
  487.                                           0)) < 66 /* sizeof(dimsinfo)*/) {
  488.           I_Error ("Can't GetDisplayInfoData() for mode %08x, got %d bytes",
  489.                    mode, nbytes);
  490.         }
  491.  
  492.         video_is_cyber_mode = 0;
  493.         if (CyberGfxBase != NULL)
  494.           video_is_cyber_mode = IsCyberModeID (mode);
  495.  
  496.         video_is_native = ((GfxBase->LibNode.lib_Version < 39 ||
  497.                           (dispinfo.PropertyFlags & DIPF_IS_EXTRAHALFBRITE) != 0 ||
  498.                           (dispinfo.PropertyFlags & DIPF_IS_AA) != 0 ||
  499.                           (dispinfo.PropertyFlags & DIPF_IS_ECS) != 0 ||
  500.                           (dispinfo.PropertyFlags & DIPF_IS_DBUFFER) != 0) &&
  501.                           !video_is_cyber_mode &&
  502.                           (dispinfo.PropertyFlags & DIPF_IS_FOREIGN) == 0);
  503.  
  504.         /* manual overrides */
  505.         if (M_CheckParm ("-rtg"))
  506.           video_is_native = FALSE;
  507.         else if (M_CheckParm ("-native"))
  508.           video_is_native = TRUE;
  509.  
  510.         printf ("Screen Mode $%08x is ", mode);
  511.         printf (" 8-BIT");
  512.         if (video_is_native)
  513.           printf (" Native-Planar");
  514.         if (video_is_cyber_mode)
  515.           printf (" CyberGraphX");
  516.         printf ("\n");
  517.  
  518.         video_depth = 8;
  519.  
  520.         rect.MinX = 0;
  521.         rect.MinY = 0;
  522.         rect.MaxX = SCREENWIDTH - 1;
  523.         rect.MaxY = SCREENHEIGHT - 1;
  524.  
  525.  
  526.         if (video_is_cyber_mode && M_CheckParm ("-directcgx"))
  527.           video_is_directcgx = TRUE;
  528.  
  529.         if ((video_screen = OpenScreenTags (NULL,
  530.               SA_Type,        CUSTOMSCREEN,
  531.               SA_DisplayID,   mode,
  532.               SA_DClip,       (ULONG)&rect,
  533.               SA_Width,       SCREENWIDTH,
  534.               SA_Height,      SCREENHEIGHT,
  535.               SA_Depth,       video_depth,
  536.               SA_Font,        (ULONG)&topaz8,
  537.               /* SA_Draggable,FALSE, */
  538.               /* SA_AutoScroll,FALSE, */
  539.               /* SA_Exclusive,TRUE, */
  540.               SA_Quiet,       TRUE,
  541.               TAG_DONE,       0)) == NULL) {
  542.           I_Error ("OpenScreen() failed");
  543.         }
  544.  
  545.         if (video_is_native) {
  546.           SBuffer[0] = AllocScreenBuffer (video_screen, NULL, SB_SCREEN_BITMAP);
  547.           SBuffer[1] = AllocScreenBuffer (video_screen, NULL, 0);
  548.           SBuffer[2] = AllocScreenBuffer (video_screen, NULL, 0);
  549.           NextSBuffer = SBuffer[1];
  550.         }
  551.  
  552.         if (video_is_directcgx) {
  553.           video_bitmap_handle = LockBitMapTags (video_screen->ViewPort.RasInfo->BitMap,
  554.                                                 LBMI_WIDTH,       (ULONG)&width,
  555.                                                 LBMI_DEPTH,       (ULONG)&depth,
  556.                                                 LBMI_PIXFMT,      (ULONG)&pixfmt,
  557.                                                 TAG_DONE);
  558.           UnLockBitMap (video_bitmap_handle);
  559.           if (/* width != SCREENWIDTH || */
  560.               depth != video_depth ||
  561.               pixfmt != PIXFMT_LUT8) {
  562.             I_Error ("ScreenMode of width %d, depth %d, pixfmt %d cannot be used with -directcgx",
  563.                      width, depth, pixfmt);
  564.           }
  565.         }
  566. #ifdef GRAFFITI
  567.         }
  568. #endif
  569.       idcmp = IDCMP_RAWKEY;
  570.       wflags = WFLG_ACTIVATE | WFLG_BORDERLESS | WFLG_RMBTRAP | WFLG_NOCAREREFRESH |
  571.                             WFLG_SIMPLE_REFRESH;
  572.       if (M_CheckParm("-mouse") != 0) {
  573.         idcmp |= IDCMP_MOUSEMOVE | IDCMP_DELTAMOVE | IDCMP_MOUSEBUTTONS;
  574.         wflags |= WFLG_REPORTMOUSE;
  575.       }
  576.  
  577.       if ((video_window = OpenWindowTags (NULL,
  578.             WA_Left,         0,
  579.             WA_Top,          0,
  580.             WA_Width,        SCREENWIDTH,
  581.             WA_Height,       SCREENHEIGHT,
  582.             WA_IDCMP,        idcmp,
  583.             WA_Flags,        wflags,
  584.             WA_CustomScreen, (ULONG)video_screen,
  585.             TAG_DONE)) == NULL) {
  586.         I_Error ("OpenWindow() failed");
  587.       }
  588.  
  589.       InitBitMap (&video_tmp_bm, video_depth, SCREENWIDTH, 1);
  590.       for (depth = 0; depth < video_depth; depth++)
  591.         if ((video_tmp_bm.Planes[depth] = (PLANEPTR)AllocRaster (SCREENWIDTH, 1)) == NULL)
  592.           I_Error ("AllocRaster() failed");
  593.       video_temprp = *video_window->RPort;
  594.       video_temprp.Layer = NULL;
  595.       video_temprp.BitMap = &video_tmp_bm;
  596.  
  597.       if ((emptypointer = AllocVec (16, MEMF_CHIP+MEMF_CLEAR)) == NULL)
  598.         I_Error ("Couldn't allocate chip memory for pointer");
  599.  
  600.       if (!M_CheckParm ("-mousepointer"))
  601.         SetPointer (video_window, emptypointer, 1, 16, 0, 0);
  602. #ifdef CHUNKYPPC
  603.     }
  604. #endif
  605.  
  606.   I_RecalcPalettes ();
  607.  
  608.   /* keyboard & joystick initialisation */
  609.  
  610.   video_is_rawkey = M_CheckParm ("-rawkey");
  611.  
  612.   if (M_CheckParm ("-sega3") != 0)
  613.     sega3_selected = TRUE;
  614.  
  615.   if (M_CheckParm ("-sega6") != 0)
  616.     sega6_selected = TRUE;
  617.  
  618.   if (M_CheckParm ("-joypad") != 0) {
  619.  
  620.     if ((LowLevelBase = OpenLibrary ("lowlevel.library", 0)) == NULL)
  621.       I_Error ("-joypad option specified and can't open lowlevel.library");
  622.  
  623.   } else if (M_CheckParm("-nojoy") == 0) {
  624.  
  625.     if ((gameport_mp = CreateMsgPort ()) == NULL ||
  626.         (gameport_io = (struct IOStdReq *)CreateIORequest (gameport_mp,
  627.                                               sizeof(struct IOStdReq))) == NULL ||
  628.         OpenDevice ("gameport.device", 1, (struct IORequest *)gameport_io, 0) != 0)
  629.       I_Error ("Can't open gameport.device");
  630.  
  631.     gameport_is_open = TRUE;
  632.  
  633.     Forbid ();
  634.  
  635.     gameport_io->io_Command = GPD_ASKCTYPE;
  636.     gameport_io->io_Length = 1;
  637.     gameport_io->io_Data = &gameport_ct;
  638.     DoIO ((struct IORequest *)gameport_io);
  639.  
  640.     if (gameport_ct != GPCT_NOCONTROLLER) {
  641.  
  642.       Permit ();
  643.       fprintf (stderr, "Another task is using the gameport!  Joystick disabled");
  644.             fflush(stderr);
  645.       CloseDevice ((struct IORequest *)gameport_io);
  646.       gameport_is_open = FALSE;
  647.  
  648.     } else {
  649.  
  650.       gameport_ct = GPCT_ABSJOYSTICK;
  651.       gameport_io->io_Command = GPD_SETCTYPE;
  652.       gameport_io->io_Length = 1;
  653.       gameport_io->io_Data = &gameport_ct;
  654.       DoIO ((struct IORequest *)gameport_io);
  655.  
  656.       Permit ();
  657.  
  658.       gameport_io->io_Command = GPD_SETTRIGGER;
  659.       gameport_io->io_Length = sizeof(struct GamePortTrigger);
  660.       gameport_io->io_Data = &gameport_gpt;
  661.       DoIO ((struct IORequest *)gameport_io);
  662.  
  663.       gameport_io->io_Command = GPD_READEVENT;
  664.       gameport_io->io_Length = sizeof (struct InputEvent);
  665.       gameport_io->io_Data = &gameport_ie;
  666.       SendIO ((struct IORequest *)gameport_io);
  667.       gameport_io_in_progress = TRUE;
  668.     }
  669.   }
  670. }
  671.  
  672. /**********************************************************************/
  673. void I_ShutdownGraphics (void)
  674. {
  675.   int depth;
  676.  
  677.     if (video_smr != NULL) {
  678.         FreeAslRequest (video_smr);
  679.     video_smr = NULL;
  680.   }
  681. #ifdef CHUNKYPPC
  682.     if (msptr != NULL) {
  683.         CloseGraphics(msptr, 1);
  684.         msptr = NULL;
  685.         video_window = NULL;
  686.     }
  687. #ifdef WARPUP
  688.     if (ChunkyPPCBase != NULL) {
  689.         CloseLibrary(ChunkyPPCBase);
  690.         ChunkyPPCBase = NULL;
  691.     }
  692. #endif
  693. #endif
  694.   if (LowLevelBase != NULL) {
  695.     CloseLibrary (LowLevelBase);
  696.     LowLevelBase = NULL;
  697.   }
  698.   if (gameport_io_in_progress) {
  699.     AbortIO ((struct IORequest *)gameport_io);
  700.     WaitIO ((struct IORequest *)gameport_io);
  701.     gameport_io_in_progress = FALSE;
  702.     gameport_ct = GPCT_NOCONTROLLER;
  703.     gameport_io->io_Command = GPD_SETCTYPE;
  704.     gameport_io->io_Length = 1;
  705.     gameport_io->io_Data = &gameport_ct;
  706.     DoIO ((struct IORequest *)gameport_io);
  707.   }
  708.   if (gameport_is_open) {
  709.     CloseDevice ((struct IORequest *)gameport_io);
  710.     gameport_is_open = FALSE;
  711.   }
  712.   if (gameport_io != NULL) {
  713.     DeleteIORequest ((struct IORequest *)gameport_io);
  714.     gameport_io = NULL;
  715.   }
  716.   if (gameport_mp != NULL) {
  717.     DeleteMsgPort (gameport_mp);
  718.     gameport_mp = NULL;
  719.   }
  720.   if (video_is_native) {
  721.     if (SBuffer[0] != NULL)
  722.       FreeScreenBuffer (video_screen, SBuffer[0]);
  723.     if (SBuffer[1] != NULL)
  724.       FreeScreenBuffer (video_screen, SBuffer[1]);
  725.     if (SBuffer[2] != NULL)
  726.       FreeScreenBuffer (video_screen, SBuffer[2]);
  727.     SBuffer[0] = NULL;
  728.     SBuffer[1] = NULL;
  729.     SBuffer[2] = NULL;
  730.   }
  731.   if (video_window != NULL) {
  732.     ClearPointer (video_window);
  733.     CloseWindow (video_window);
  734.     video_window = NULL;
  735.   }
  736.   if (emptypointer != NULL) {
  737.     FreeVec (emptypointer);
  738.     emptypointer = NULL;
  739.   }
  740. #ifdef GRAFFITI
  741.   if (video_grf_screen != NULL) {
  742.     CloseChunkyScreen (video_grf_screen);
  743.     video_grf_screen = NULL;
  744.     video_screen = NULL;
  745.   }
  746.   if (GraffitiBase != NULL) {
  747.     CloseLibrary (GraffitiBase);
  748.     GraffitiBase = NULL;
  749.      }
  750. #endif
  751.   if (video_screen != NULL) {
  752.     CloseScreen (video_screen);
  753.     video_screen = NULL;
  754.   }
  755.   for (depth = 0; depth < video_depth; depth++) {
  756.     if (video_tmp_bm.Planes[depth] != NULL) {
  757.       FreeRaster (video_tmp_bm.Planes[depth], SCREENWIDTH, 1);
  758.       video_tmp_bm.Planes[depth] = NULL;
  759.     }
  760.   }
  761.   if (KeymapBase != NULL) {
  762.     CloseLibrary (KeymapBase);
  763.     KeymapBase = NULL;
  764.   }
  765.   if (CyberGfxBase != NULL) {
  766.     CloseLibrary (CyberGfxBase);
  767.     CyberGfxBase = NULL;
  768.   }
  769.     if (AslBase != NULL) {
  770.         CloseLibrary(AslBase);
  771.         AslBase = NULL;
  772.     }
  773. }
  774.  
  775. /**********************************************************************/
  776. // recalculate colourtable[][] after changing usegamma
  777. void I_RecalcPalettes (void)
  778. {
  779.   int p, i;
  780.   byte *palette;
  781.   static int lu_palette;
  782.  
  783.   lu_palette = W_GetNumForName ("PLAYPAL");
  784.   for (p = 0; p < NUMPALETTES; p++) {
  785.     palette = (byte *) W_CacheLumpNum (lu_palette, PU_STATIC)+p*768;
  786. #ifdef GRAFFITI
  787.     if (video_graffiti != 0) {
  788.       for (i = 0; i < 256; i++)
  789.         video_colourtable[p][i] =
  790.                     (((UBYTE)gammatable[usegamma][palette[3*i+0]]) << 16) +
  791.                     (((UBYTE)gammatable[usegamma][palette[3*i+1]]) << 8) +
  792.                      ((UBYTE)gammatable[usegamma][palette[3*i+2]]);
  793.     } else {
  794. #endif
  795.       i = 3 * 256 - 1;
  796.       video_colourtable[p][i + 2] = 0;
  797.       do {
  798.         // Better to define c locally here instead of for the whole function:
  799.         ULONG c = gammatable[usegamma][palette[i]];
  800.         c += (c << 8);
  801.         video_colourtable[p][i + 1] = (c << 16) + c;
  802.       } while (--i >= 0);
  803.       video_colourtable[p][0] = (256 << 16) + 0;
  804. #ifdef GRAFFITI
  805.     }
  806. #endif
  807.   }
  808. }
  809.  
  810. /**********************************************************************/
  811. // Takes full 8 bit values.
  812. void I_SetPalette (byte *palette, int palette_index)
  813. {
  814.   video_palette_changed = 1;
  815.   video_palette_index = palette_index;
  816. }
  817.  
  818. /**********************************************************************/
  819. // Called by anything that renders to screens[0] (except 3D view)
  820. void I_MarkRect (int left, int top, int width, int height)
  821. {
  822.   M_AddToBox (dirtybox, left, top);
  823.   M_AddToBox (dirtybox, left + width - 1, top + height - 1);
  824. }
  825.  
  826. /**********************************************************************/
  827. void I_StartUpdate (void)
  828. {
  829. }
  830.  
  831. /**********************************************************************/
  832. void I_UpdateNoBlit (void)
  833. {
  834. }
  835.  
  836. /**********************************************************************/
  837. void I_FinishUpdate (void)
  838. /* This needs optimising to copy just the parts that changed,
  839.    especially if the user has shrunk the playscreen. */
  840. {
  841.   int top, left, width, height;
  842.   int stat, i, j;
  843.   UBYTE *base_address;
  844.   total_frames++;
  845.  
  846. #ifdef CHUNKYPPC
  847.     if (video_is_chunkyppc) {
  848.         if (video_palette_changed !=0) {
  849.             LoadColors(&ms,video_colourtable[video_palette_index]);
  850.             video_palette_changed = 0;
  851.         }
  852.         start_timer();
  853.         if (ms.video_is_native_mode) {
  854.             switch (ms.numbuffers) {
  855.                 case 1:
  856.                     CallChunkyCopy(&ms, (void *)ms.bitmapa, screens[0], PIXFMT_LUT8, 0, 0);
  857.                     break;
  858.                 case 2:
  859.                     if (ms.bufnum == 0)
  860.                         CallChunkyCopy(&ms, (void *)ms.bitmapb, screens[0], PIXFMT_LUT8, 0, 0);
  861.                     else
  862.                         CallChunkyCopy(&ms, (void *)ms.bitmapa, screens[0], PIXFMT_LUT8, 0, 0);
  863.                     DoubleBuffer(&ms);
  864.                     break;
  865.                 case 3:
  866.                     if (ms.bufnum == 0)
  867.                         CallChunkyCopy(&ms, (void *)ms.bitmapb, screens[0], PIXFMT_LUT8, 0, 0);
  868.                     else if (ms.bufnum == 1)
  869.                         CallChunkyCopy(&ms, (void *)ms.bitmapc, screens[0], PIXFMT_LUT8, 0, 0);
  870.                     else
  871.                         CallChunkyCopy(&ms, (void *)ms.bitmapa, screens[0], PIXFMT_LUT8, 0, 0);
  872.                     DoubleBuffer(&ms);
  873.                     break;
  874.             }
  875.         }
  876.         else {
  877.             switch (ms.numbuffers) {
  878.                 case 1:
  879.                     CallChunkyCopy(&ms, ms.screen, screens[0], PIXFMT_LUT8, 0, 0);
  880.                     break;
  881.                 case 2:
  882.                     if (ms.bufnum == 0)
  883.                         CallChunkyCopy(&ms, ms.screenb, screens[0], PIXFMT_LUT8, 0, 0);
  884.                     else
  885.                         CallChunkyCopy(&ms, ms.screen, screens[0], PIXFMT_LUT8, 0, 0);
  886.                     DoubleBuffer(&ms);
  887.                     break;
  888.                 case 3:
  889.                     if (ms.bufnum == 0)
  890.                         CallChunkyCopy(&ms, ms.screenb, screens[0], PIXFMT_LUT8, 0, 0);
  891.                     else if (ms.bufnum == 1)
  892.                         CallChunkyCopy(&ms, ms.screenc, screens[0], PIXFMT_LUT8, 0, 0);
  893.                     else
  894.                         CallChunkyCopy(&ms, ms.screen, screens[0], PIXFMT_LUT8, 0, 0);
  895.                     DoubleBuffer(&ms);
  896.                     break;
  897.             }
  898.         }
  899.         chunkyppc_time += end_timer();
  900.         if (video_doing_fps) 
  901.             video_do_fps (video_window->RPort, 0);
  902.         return;
  903.     }
  904. #endif
  905. #ifdef GRAFFITI
  906.   if (video_graffiti != 0) {
  907.     start_timer();
  908.     CopyChunkyScreen (video_grf_screen, screens[0]);
  909.     SetChunkyPalette (video_grf_screen,
  910.                       (long *)video_colourtable[video_palette_index]);
  911.     video_palette_changed = 0;
  912.     ccs_time += end_timer();
  913.     return;
  914.   }
  915. #endif
  916.  
  917.   if (video_is_directcgx) {
  918.     if (video_palette_changed != 0) {
  919.       LoadRGB32 (&video_screen->ViewPort,
  920.                  video_colourtable[video_palette_index]);
  921.       video_palette_changed = 0;
  922.     }
  923.     start_timer ();
  924.     video_bitmap_handle = LockBitMapTags (video_screen->ViewPort.RasInfo->BitMap,
  925.                                             LBMI_BASEADDRESS, (ULONG)&base_address,
  926.                                             TAG_DONE);
  927.     memcpy (base_address, screens[0], SCREENWIDTH * SCREENHEIGHT);
  928.     UnLockBitMap (video_bitmap_handle);
  929.  
  930.     lock_time += end_timer ();
  931.     if (video_doing_fps)
  932.       video_do_fps (video_window->RPort, 0);
  933.     return;
  934.   }
  935.  
  936.   /* update only the viewwindow and dirtybox when gamestate == GS_LEVEL */
  937.   if (gamestate == GS_LEVEL) {
  938.     if (dirtybox[BOXLEFT] < viewwindowx)
  939.       left = dirtybox[BOXLEFT];
  940.     else
  941.       left = viewwindowx;
  942.     if (dirtybox[BOXRIGHT] + 1 > viewwindowx + scaledviewwidth)
  943.       width = dirtybox[BOXRIGHT] + 1 - left;
  944.     else
  945.       width = viewwindowx + scaledviewwidth - left;
  946.     if (dirtybox[BOXBOTTOM] < viewwindowy) /* BOXBOTTOM is really the top! */
  947.       top = dirtybox[BOXBOTTOM];
  948.     else
  949.       top = viewwindowy;
  950.     if (dirtybox[BOXTOP] + 1 > viewwindowy + viewheight)
  951.       height = dirtybox[BOXTOP] + 1 - top;
  952.     else
  953.       height = viewwindowy + viewheight - top;
  954.     M_ClearBox (dirtybox);
  955. #ifdef RANGECHECK
  956.     if (left < 0 || left + width > SCREENWIDTH ||
  957.         top < 0 || top + height > SCREENHEIGHT)
  958.       I_Error ("I_FinishUpdate: Box out of range: %d %d %d %d",
  959.                left, top, width, height);
  960. #endif
  961.   } else {
  962.     left = 0;
  963.     top = 0;
  964.     width = SCREENWIDTH;
  965.     height = SCREENHEIGHT;
  966.   }
  967.  
  968.   /* not directcgx or graffiti */
  969.   if (video_palette_changed != 0) {
  970.     LoadRGB32 (&video_screen->ViewPort,
  971.                video_colourtable[video_palette_index]);
  972.     video_palette_changed = 0;
  973.   }
  974.   if (video_is_native) {
  975.     start_timer();
  976.     for (i=0, j=(int)screens[0]; i<SCREENHEIGHT; i++, j+=SCREENWIDTH)
  977.       ppc_c2p_line (i, j, NextSBuffer->sb_BitMap, (SCREENWIDTH+31)>>5);
  978.     stat = ChangeScreenBuffer(video_screen, NextSBuffer);
  979.     if (NextSBuffer == SBuffer[0])
  980.       NextSBuffer = SBuffer[1];
  981.     else if (NextSBuffer == SBuffer[1])
  982.       NextSBuffer = SBuffer[2];
  983.     else
  984.       NextSBuffer = SBuffer[0];
  985.     c2p_time += end_timer();
  986.   } else {
  987.     start_timer();
  988.     WritePixelArray8 (video_window->RPort, 0, top, SCREENWIDTH-1,
  989.                       top+height-1, &screens[0][SCREENWIDTH * top],
  990.                       &video_temprp);
  991.     wpa8_time += end_timer();
  992.   }
  993.   if (video_doing_fps)
  994.     video_do_fps (video_window->RPort, 0);
  995. }
  996.  
  997. /**********************************************************************/
  998. // Wait for vertical retrace or pause a bit.  Use when quit game.
  999. void I_WaitVBL(int count)
  1000. {
  1001.   for ( ; count > 0; count--)
  1002.     WaitTOF();
  1003. }
  1004.  
  1005. /**********************************************************************/
  1006. void I_ReadScreen (byte* scr)
  1007. {
  1008.   memcpy (scr, screens[0], SCREENWIDTH * SCREENHEIGHT);
  1009. }
  1010.  
  1011. /**********************************************************************/
  1012. void I_BeginRead (void)
  1013. {
  1014. }
  1015.  
  1016. /**********************************************************************/
  1017. void I_EndRead (void)
  1018. {
  1019. }
  1020.  
  1021. /**********************************************************************/
  1022.  
  1023. int xlate_key (UWORD rawkey, UWORD qualifier, APTR *eventptr)
  1024. {
  1025.   char buffer[4], c;
  1026.   struct InputEvent ie;
  1027.   static int xlate[0x68] = {
  1028.     '`', '1', '2', '3', '4', '5', '6', '7',
  1029.     '8', '9', '0', KEY_MINUS, KEY_EQUALS, '\\', 0, '0',
  1030.     'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
  1031.     'o', 'p', KEY_F11, KEY_F12, 0, '0', '2', '3',
  1032.     'a', 's', 'd', 'f', 'g', 'h', 'j', 'k',
  1033.     'l', ';', '\'', KEY_ENTER, 0, '4', '5', '6',
  1034.     KEY_RSHIFT, 'z', 'x', 'c', 'v', 'b', 'n', 'm',
  1035.     ',', '.', '/', 0, '.', '7', '8', '9',
  1036.     ' ', KEY_BACKSPACE, KEY_TAB, KEY_ENTER, KEY_ENTER, KEY_ESCAPE, KEY_F11,
  1037.     0, 0, 0, KEY_MINUS, 0, KEY_UPARROW, KEY_DOWNARROW, KEY_RIGHTARROW, KEY_LEFTARROW,
  1038.     KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7, KEY_F8,
  1039.     KEY_F9, KEY_F10, '(', ')', '/', '*', KEY_EQUALS, KEY_PAUSE,
  1040.     KEY_RSHIFT, KEY_RSHIFT, 0, KEY_RCTRL, KEY_LALT, KEY_RALT, 0, KEY_RCTRL
  1041.   };
  1042.  
  1043.   if (video_is_rawkey)
  1044.     if (rawkey < 0x68)
  1045.       return xlate[rawkey];
  1046.     else
  1047.       return 0;
  1048.   else
  1049.     if (rawkey > 0x00 && rawkey < 0x0a) // '1'..'9', no SHIFT French keyboards
  1050.       return '0' + rawkey;
  1051.     else if (rawkey == 0x0a)            // '0'
  1052.       return '0';
  1053.     else if (rawkey < 0x40) {
  1054.       ie.ie_Class = IECLASS_RAWKEY;
  1055.       ie.ie_Code = rawkey;
  1056.       ie.ie_Qualifier = qualifier;
  1057.       ie.ie_EventAddress = *eventptr;
  1058.       if (MapRawKey (&ie, buffer, sizeof(buffer), NULL) > 0) {
  1059.         c = buffer[0];
  1060.         if (c >= '0' && c <= '9')       /* numeric pad */
  1061.           switch (c) {
  1062.           case '0':
  1063.             return ' ';
  1064.           case '1':
  1065.             return ',';
  1066.           case '2':
  1067.             return KEY_RCTRL;
  1068.           case '3':
  1069.             return '.';
  1070.           case '4':
  1071.             return KEY_LEFTARROW;
  1072.           case '5':
  1073.             return KEY_DOWNARROW;
  1074.           case '6':
  1075.             return KEY_RIGHTARROW;
  1076.           case '7':
  1077.             return ',';
  1078.           case '8':
  1079.             return KEY_UPARROW;
  1080.           case '9':
  1081.             return '.';
  1082.           }
  1083.         else if (c >= 'A' && c <= 'Z')
  1084.           return c - 'A' + 'a';
  1085.         else if (c == '<')
  1086.           return ',';
  1087.         else if (c == '>')
  1088.           return '.';
  1089.         else if (c == '-')
  1090.           return KEY_MINUS;
  1091.         else if (c == '=')
  1092.           return KEY_EQUALS;
  1093.         else if (c == '[')
  1094.           return KEY_F11;
  1095.         else if (c == ']')
  1096.           return KEY_F12;
  1097.         else if (c == '\r')
  1098.           return KEY_ENTER;
  1099.         else if (c == '\n')
  1100.           return KEY_ENTER;
  1101.         else
  1102.           return c;
  1103.       } else
  1104.         return 0;
  1105.     } else if (rawkey < 0x68)
  1106.       return xlate[rawkey];
  1107.     else
  1108.       return 0;
  1109.  
  1110.     return 0;
  1111. }
  1112.  
  1113. /**********************************************************************/
  1114. void amiga_getevents (void)
  1115. {
  1116.   event_t event;
  1117.   ULONG class;
  1118.   UWORD code;
  1119.   WORD mousex, mousey;
  1120.   struct IntuiMessage *msg;
  1121.   static ULONG previous = 0;
  1122.   static event_t joyevent = {0}, mouseevent = {0};
  1123.   ULONG currSega;
  1124.   int doomkey = 0;
  1125.  
  1126.   if (video_window != NULL) {
  1127.     while ((msg = (struct IntuiMessage *)GetMsg (video_window->UserPort)) != NULL) {
  1128.       class = msg->Class;
  1129.       code = msg->Code;
  1130.       mousex = msg->MouseX;
  1131.       mousey = msg->MouseY;
  1132.       if (class == IDCMP_RAWKEY) {
  1133.         if ((code & 0x80) != 0) {
  1134.           code &= ~0x80;
  1135.       event.type = ev_keyup;
  1136.         } else {
  1137.           event.type = ev_keydown;
  1138.         }
  1139.         if (code < 0x68)
  1140.           doomkey = xlate_key (code, msg->Qualifier, msg->IAddress);
  1141.       }
  1142.       ReplyMsg ((struct Message *)msg);  /* reply after xlating key */
  1143.       if (class == IDCMP_RAWKEY) {
  1144.         if (code < 0x68 && doomkey != 0) {
  1145.           event.data1 = doomkey;
  1146.           D_PostEvent (&event);
  1147.           /* printf ("key %02x -> %02x\n", code, doomkey); */
  1148.         }
  1149.       } else if (class == IDCMP_MOUSEMOVE) {
  1150.         mouseevent.type = ev_mouse;
  1151.         mouseevent.data2 = (mousex << 3);
  1152.         mouseevent.data3 = -(mousey << 5);
  1153.         D_PostEvent (&mouseevent);
  1154.       } else if (class == IDCMP_MOUSEBUTTONS) {
  1155.         mouseevent.type = ev_mouse;
  1156.         switch (code) {
  1157.           case SELECTDOWN:
  1158.             mouseevent.data1 |= 1;
  1159.             break;
  1160.           case SELECTUP:
  1161.             mouseevent.data1 &= ~1;
  1162.             break;
  1163.           case MENUDOWN:
  1164.             mouseevent.data1 |= 2;
  1165.             break;
  1166.           case MENUUP:
  1167.             mouseevent.data1 &= ~2;
  1168.             break;
  1169.           case MIDDLEDOWN:
  1170.             mouseevent.data1 |= 4;
  1171.             break;
  1172.           case MIDDLEUP:
  1173.             mouseevent.data1 &= ~4;
  1174.             break;
  1175.           default:
  1176.             break;
  1177.         }
  1178.         D_PostEvent (&mouseevent);
  1179.       }
  1180.     }
  1181.   }
  1182.  
  1183.   if (gameport_is_open && gameport_io_in_progress) {
  1184.     while (GetMsg (gameport_mp) != NULL) {
  1185.       switch (gameport_ie.ie_Code) {
  1186.         case IECODE_LBUTTON:
  1187.           joyevent.data1 |= 1;
  1188.           break;
  1189.         case IECODE_LBUTTON | IECODE_UP_PREFIX:
  1190.           joyevent.data1 &= ~1;
  1191.           break;
  1192.         case IECODE_RBUTTON:
  1193.           joyevent.data1 |= 2;
  1194.           break;
  1195.         case IECODE_RBUTTON | IECODE_UP_PREFIX:
  1196.           joyevent.data1 &= ~2;
  1197.           break;
  1198.         case IECODE_MBUTTON:
  1199.           joyevent.data1 |= 4;
  1200.           break;
  1201.         case IECODE_MBUTTON | IECODE_UP_PREFIX:
  1202.           joyevent.data1 &= ~4;
  1203.           break;
  1204.         case IECODE_NOBUTTON:
  1205.           joyevent.data2 = gameport_ie.ie_X;
  1206.           joyevent.data3 = gameport_ie.ie_Y;
  1207.           break;
  1208.         default:
  1209.           break;
  1210.       }
  1211.       joyevent.type = ev_joystick;
  1212.       D_PostEvent (&joyevent);
  1213.       gameport_io->io_Command = GPD_READEVENT;
  1214.       gameport_io->io_Length = sizeof (struct InputEvent);
  1215.       gameport_io->io_Data = &gameport_ie;
  1216.       SendIO ((struct IORequest *)gameport_io);
  1217.     }
  1218.   }
  1219.  
  1220.   /* CD32 joypad handler code supplied by Gabry (ggreco@iol.it) */
  1221.  
  1222.   if (LowLevelBase != NULL) {
  1223.     event_t joyevent;
  1224.     ULONG joypos = ReadJoyPort (1);
  1225.  
  1226.     if (previous == joypos)
  1227.       return;
  1228.  
  1229.     joyevent.type = ev_joystick;
  1230.     joyevent.data1 = joyevent.data2 = joyevent.data3 = 0;
  1231.  
  1232.     if (joypos & JPF_BUTTON_RED)
  1233.       joyevent.data1 |= 1;
  1234.     else
  1235.       joyevent.data1 &= ~1;
  1236.  
  1237.     if (joypos & JP_DIRECTION_MASK) {
  1238.       if (joypos & JPF_JOY_LEFT) {
  1239.         joyevent.data2 = -1;
  1240.       } else if (joypos & JPF_JOY_RIGHT) {
  1241.         joyevent.data2 = 1;
  1242.       }
  1243.       if (joypos & JPF_JOY_UP) {
  1244.         joyevent.data3 = -1;
  1245.       } else if (joypos & JPF_JOY_DOWN) {
  1246.         joyevent.data3 = 1;
  1247.       }
  1248.     }
  1249.  
  1250.     if (joypos & JP_TYPE_GAMECTLR) {
  1251.       event_t event;
  1252.  
  1253.       // Play/Pause = ESC (Menu)
  1254.       if (joypos & JPF_BUTTON_PLAY && !(previous & JPF_BUTTON_PLAY)) {
  1255.         event.type = ev_keydown;
  1256.         event.data1 = KEY_ESCAPE;
  1257.         D_PostEvent (&event);
  1258.       } else if (previous & JPF_BUTTON_PLAY) {
  1259.         event.type = ev_keyup;
  1260.         event.data1 = KEY_ESCAPE;
  1261.         D_PostEvent (&event);
  1262.       }
  1263.  
  1264.       // YELLOW = SHIFT (button 2) (Run)
  1265.       if (joypos & JPF_BUTTON_YELLOW)
  1266.         joyevent.data1 |= 4;
  1267.       else
  1268.         joyevent.data1 &= ~4;
  1269.  
  1270.       // BLUE = SPACE (button 3) (Open/Operate)
  1271.  
  1272.       if (joypos & JPF_BUTTON_BLUE)
  1273.         joyevent.data1 |= 8;
  1274.       else
  1275.         joyevent.data1 &= ~8;
  1276.  
  1277.       // GREEN = RETURN (show msg)
  1278.  
  1279.       if (joypos & JPF_BUTTON_GREEN && !(previous&JPF_BUTTON_GREEN)) {
  1280.         event.type = ev_keydown;
  1281.         event.data1 = 13;
  1282.         D_PostEvent (&event);
  1283.       } else if (previous & JPF_BUTTON_GREEN) {
  1284.         event.type = ev_keyup;
  1285.         event.data1 = 13;
  1286.         D_PostEvent (&event);
  1287.       }
  1288.  
  1289.       // FORWARD & REVERSE - ALT (Button1) Strafe left/right
  1290.  
  1291.       if (joypos & JPF_BUTTON_FORWARD) {
  1292.         joyevent.data1 |= 2;
  1293.         joyevent.data2 = 1;
  1294.       } else if (joypos & JPF_BUTTON_REVERSE) {
  1295.         joyevent.data1 |=2;
  1296.         joyevent.data2=-1;
  1297.       } else
  1298.         joyevent.data1 &= ~2;
  1299.     }
  1300.  
  1301.     D_PostEvent (&joyevent);
  1302.  
  1303.     previous = joypos;
  1304.   }
  1305.  
  1306.   /* SEGA joypad handler code by Joe Fenton, loosely based on CD32 handling */
  1307.  
  1308.   if (sega3_selected || sega6_selected) {
  1309.     event_t joyevent, event;
  1310.  
  1311.     if (sega3_selected) {
  1312.       currSega = Sega3 ();
  1313.     } else {
  1314.       currSega = Sega6 ();
  1315.     }
  1316.  
  1317.     if (prevSega == currSega)
  1318.       return;
  1319.  
  1320.     joyevent.type = ev_joystick;
  1321.     joyevent.data1 = joyevent.data2 = joyevent.data3 = 0;
  1322.  
  1323.     // B = fire
  1324.     if (currSega & 0x10)
  1325.       joyevent.data1 |= 1;
  1326.     else
  1327.       joyevent.data1 &= ~1;
  1328.  
  1329.     // directionals
  1330.     if (currSega & 0xF) {
  1331.       if (currSega & 4) {
  1332.         joyevent.data2 = -1;
  1333.       } else if (currSega & 8) {
  1334.         joyevent.data2 = 1;
  1335.       }
  1336.       if (currSega & 1) {
  1337.         joyevent.data3 = -1;
  1338.       } else if (currSega & 2) {
  1339.         joyevent.data3 = 1;
  1340.       }
  1341.     }
  1342.  
  1343.     // Mode = ESC (Menu)
  1344.     if (currSega & 0x80000 && !(prevSega & 0x80000)) {
  1345.       event.type = ev_keydown;
  1346.       event.data1 = KEY_ESCAPE;
  1347.       D_PostEvent (&event);
  1348.     } else if (prevSega & 0x80000) {
  1349.       event.type = ev_keyup;
  1350.       event.data1 = KEY_ESCAPE;
  1351.       D_PostEvent (&event);
  1352.     }
  1353.  
  1354.     // Y = SHIFT (Run)
  1355.     if (currSega & 0x20000)
  1356.       joyevent.data1 |= 4;
  1357.     else
  1358.       joyevent.data1 &= ~4;
  1359.  
  1360.     // Start = SPACE (Open/Operate)
  1361.     if (currSega & 0x2000)
  1362.       joyevent.data1 |= 8;
  1363.     else
  1364.       joyevent.data1 &= ~8;
  1365.  
  1366.     // A & C - ALT (Button1) Strafe left/right
  1367.     if (currSega & 0x20) {
  1368.       joyevent.data1 |= 2;
  1369.       joyevent.data2 = 1;
  1370.     } else if (currSega & 0x1000) {
  1371.       joyevent.data1 |=2;
  1372.       joyevent.data2=-1;
  1373.     } else
  1374.       joyevent.data1 &= ~2;
  1375.  
  1376.     // X = RETURN (show msg)
  1377.     if (currSega & 0x40000 && !(prevSega&0x40000)) {
  1378.       event.type = ev_keydown;
  1379.       event.data1 = 13;
  1380.       D_PostEvent (&event);
  1381.     } else if (prevSega & 0x40000) {
  1382.       event.type = ev_keyup;
  1383.       event.data1 = 13;
  1384.       D_PostEvent (&event);
  1385.     }
  1386.  
  1387.     // Z = TAB (show map)
  1388.     if (currSega & 0x10000 && !(prevSega&0x10000)) {
  1389.       event.type = ev_keydown;
  1390.       event.data1 = 9;
  1391.       D_PostEvent (&event);
  1392.     } else if (prevSega & 0x10000) {
  1393.       event.type = ev_keyup;
  1394.       event.data1 = 9;
  1395.       D_PostEvent (&event);
  1396.     }
  1397.  
  1398.     D_PostEvent (&joyevent);
  1399.  
  1400.     prevSega = currSega;
  1401.   }
  1402.  
  1403. }
  1404.  
  1405. /**********************************************************************/
  1406. static void calc_time (ULONG time, char *msg)
  1407. {
  1408. #ifdef __VBCC__
  1409.     printf ("Total %s = %ld us  (%ld us/frame)\n", msg, time, time / total_frames);
  1410. #else
  1411.   printf ("Total %s = %ldu us  (%ldu us/frame)\n", msg, time, time / total_frames);
  1412. #endif
  1413. }
  1414.  
  1415. /**********************************************************************/
  1416. void video_cleanup (void)
  1417. {
  1418.   I_ShutdownGraphics ();
  1419.   if (total_frames > 0) {
  1420.     printf ("Total number of frames = %u\n", total_frames);
  1421.     calc_time (wpa8_time, "WritePixelArray8 time ");
  1422.     calc_time (lock_time, "LockBitMap time       ");
  1423.     calc_time (c2p_time, "Chunky2Planar time    ");
  1424. #ifdef CHUNKYPPC
  1425.         calc_time (chunkyppc_time, "ChunkyPPC time        ");
  1426. #endif
  1427. #ifdef PROFILE
  1428.     {
  1429.       int i;
  1430.  
  1431.       for (i=0; i<32; i++)
  1432.         calc_time (profile[n][2], "Profile Time ");
  1433.     }
  1434. #endif
  1435.   }
  1436. }
  1437.  
  1438. /**********************************************************************/
  1439.